package com.pomelo.base.core.config;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionStatus;

import com.pomelo.base.core.datasource.DynamicDataSourceContextHolder;

/**
 * 事务管理器
 *
 * @author biankudingcha
 * @date: 2021-07-23
 * @since 0.5.0
 */
public class PomeloPlatformTransactionManager implements PlatformTransactionManager {

    /**
     * 日志
     */
    private static final Log LOGGER = LogFactory.getLog(PomeloPlatformTransactionManager.class);

    /**
     * 获取事务管理器
     *
     * @return PlatformTransactionManager
     */
    private PlatformTransactionManager getTargetTransactionManager() {
        String beanId = getBeanId();
        LOGGER.debug("事务管理器为:" + beanId);
        return MultiDataSourceUtil.getPlatformTransactionManager(beanId);
    }

    /**
     * 获取beanId
     *
     * @return String
     */
    private String getBeanId() {
        String dataSourceId = DynamicDataSourceContextHolder.getDataSourceId();
        String beanId = null;
        if (dataSourceId == null || "".equals(dataSourceId)
                || !DynamicDataSourceContextHolder.containsDataSourceId(dataSourceId)) {
            beanId = "PlatformTransactionManager-defaultDataSource";
        } else {
            beanId = "PlatformTransactionManager-" + dataSourceId;
        }
        return beanId;
    }

    @Override
    public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        DefaultTransactionStatus transactionStatus = (DefaultTransactionStatus) getTargetTransactionManager()
                .getTransaction(definition);
        PomeloTransactionStatus pomeloTransactionStatus = new PomeloTransactionStatus(
                transactionStatus.getTransaction(), transactionStatus.isNewTransaction(),
                transactionStatus.isNewSynchronization(), transactionStatus.isReadOnly(), transactionStatus.isDebug(),
                transactionStatus.getSuspendedResources());
        String beanId = getBeanId();
        pomeloTransactionStatus.setPlatformTransactionManagerBeanId(beanId);
        DynamicDataSourceContextHolder.setTransactionStatu(beanId, pomeloTransactionStatus);
        return pomeloTransactionStatus;
    }

    @Override
    public void commit(TransactionStatus status) throws TransactionException {
        PomeloTransactionStatus pomeloTransactionStatus = (PomeloTransactionStatus) status;
        String beanId = pomeloTransactionStatus.getPlatformTransactionManagerBeanId();
        MultiDataSourceUtil.getPlatformTransactionManager(beanId).commit(status);
        DynamicDataSourceContextHolder.removeTransactionStatu(beanId);
    }

    @Override
    public void rollback(TransactionStatus status) throws TransactionException {
        PomeloTransactionStatus pomeloTransactionStatus = (PomeloTransactionStatus) status;
        String beanId = pomeloTransactionStatus.getPlatformTransactionManagerBeanId();
        MultiDataSourceUtil.getPlatformTransactionManager(beanId).rollback(status);
        DynamicDataSourceContextHolder.removeTransactionStatu(beanId);
    }

}
